package collection;

import exception.CollectionEmptyException;

public class DCircularLinkedList <T> extends ACircularLinkedList<DNode<T>, T>{
	
	@Override
	public DNode<T> createNode(T element) 
	{
		return new DNode<T>(element);
	}

	@Override
	protected DNode<T> getNext(DNode<T> someNode) 
	{
		return someNode.getNext();
	}
	
	@Override
	public DNode<T> getPrev() 
	{
		if (cursor == null)
		{
			return null;
		}
		
		return cursor.getPrev();
	}
	
	@Override
	public DNode<T> getNext() 
	{
		if (cursor == null)
		{
			return null;
		}
		else
		{
			return cursor.getNext();
		}
	}
	
	@Override
	public void moveToPrev() 
	{
		if (cursor == null)
		{
			return ;
		}
		else
		{
			cursor = cursor.getPrev();
		}
	}

	@Override
	public void moveToNext() 
	{
		if (cursor == null)
		{
			return ;
		}
		else
		{
			cursor = cursor.getNext();
		}
	}
	
	@Override
	public void addBefore(DNode<T> someNode) 
	{
		if (cursor == null)
		{
			cursor = someNode;
			cursor.setPrev(cursor);
			cursor.setNext(cursor);
		}
		else
		{
			DNode<T> prevNode = cursor.getPrev();
			prevNode.setNext(someNode);
			someNode.setPrev(prevNode);
			someNode.setNext(cursor);
			cursor.setPrev(someNode);
		}
	}

	@Override
	public void addAfter(DNode<T> someNode) 
	{
		if (cursor == null)
		{
			cursor = someNode;
			cursor.setPrev(cursor);
			cursor.setNext(cursor);
		}
		else
		{
			DNode<T> nextNode = cursor.getNext();
			cursor.setNext(someNode);
			someNode.setPrev(cursor);
			someNode.setNext(nextNode);
			nextNode.setPrev(someNode);
		}
	}
	
	@Override
	public DNode<T> removeBefore() 
	{
		if (cursor == null)
		{
			throw new CollectionEmptyException("Circular List");
		}
		
		DNode<T> prevNode = cursor.getPrev();
		if (prevNode == cursor) // list has only one element
		{
			DNode<T> cursorNode = cursor;
			cursor = null;

			cursorNode.setPrev(null);
			cursorNode.setNext(null);
			return cursorNode;


		}
		else // list has more than one elements
		{
			DNode<T> prev2Node = prevNode.getPrev();
			prev2Node.setNext(cursor);
			cursor.setPrev(prev2Node);
			
			prevNode.setPrev(null);
			prevNode.setNext(null);
			return prevNode;
		}
	}
	
	@Override
	public DNode<T> removeAfter() 
	{
		if (cursor == null)
		{
			throw new CollectionEmptyException("Circular List") ;
		}
		
		DNode<T> nextNode = cursor.getNext();
		if (nextNode == cursor) // list has only one element
		{
			DNode<T> cursorNode = cursor;
			cursor = null;
			
			cursorNode.setPrev(null);
			cursorNode.setNext(null);
			return cursorNode;
		}
		else // list has more than one elements
		{
			DNode<T> next2Node = nextNode.getNext();
			next2Node.setPrev(cursor);
			cursor.setNext(next2Node);
			
			nextNode.setPrev(null);
			nextNode.setNext(null);
			return nextNode;
		}
	}

	@Override
	public void removeCursor() 
	{
		moveToNext();
		removeBefore();
	}

}